package jxta.chat;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.plaf.OptionPaneUI;

import jxta.chat.entities.LogOutMessage;
import jxta.chat.entities.LoginMessage;
import jxta.chat.entities.RegularMessage;
import jxta.chat.entities.UserDiscoveredMessage;
import jxta.chat.events.JxtaChatEvent;
import jxta.chat.events.JxtaChatListener;
import jxta.chat.util.Constants;
import jxta.chat.util.Constants.ChatInvitaionResponseVals;
import jxta.chat.voice.VoJxtaDialogView;
import jxta.test.JxtaManager;
import net.jxta.endpoint.Message;
import net.jxta.myjxta.ui.MyJXTAView;

public class ChatGUI extends JFrame implements java.awt.event.ActionListener{

	javax.swing.JTextArea  Messages = new javax.swing.JTextArea(10,60);
	javax.swing.JTextArea  EventMessages = new javax.swing.JTextArea(10,60);
	//javax.swing.JTextArea Input    = new javax.swing.JTextArea();
	javax.swing.JTextField Input = new javax.swing.JTextField();
	private JList peerList;
	private DefaultListModel listModel = new DefaultListModel();
	
	private VoJxtaDialogView voiceChatView = null;
	
	// TODO Check the map value
	//private Map<String, PeerNode> peers = new HashMap<String, PeerNode>(); 
	//private Map<String, PipeAdvertisement> peers = new HashMap<String, PipeAdvertisement>();
	
	int printposition = 0;
	
	JxtaManager chatManager = null;
	
	public ChatGUI(String instanceName) {
		
		chatManager = new JxtaManager(instanceName, this);
		chatManager.addOutputListener(new MessageListener());
		chatManager.addPeerListener(new PeerListener());
		chatManager.startJXTA();
		
		this.setSize(600, 400);
		this.setLocation(20, 40);		
		//chat = new Chat(this, this, inName);

		Messages.setEditable(false);
		Messages.setLineWrap(true);
		EventMessages.setEditable(false);
		EventMessages.setLineWrap(true);
		Input.addActionListener(this);
		Input.setMaximumSize(new Dimension(this.getWidth(), 50));
		Input.setMinimumSize(new Dimension(this.getWidth(), 50));
		Input.setSize(new Dimension(this.getWidth(), 50));
		Input.setFocusable(true);
		
		//Input.addKeyListener(new MessageTextAreaListener());

		javax.swing.JPanel messageArea = new javax.swing.JPanel(
				new java.awt.BorderLayout());
		javax.swing.JScrollPane messageScroll = new javax.swing.JScrollPane(
				Messages);
		messageArea.add(messageScroll, java.awt.BorderLayout.CENTER);
		messageArea.setEnabled(false);	
		
		peerList = new JList(listModel);

		javax.swing.JPanel eventMessageArea = new javax.swing.JPanel(
				new java.awt.BorderLayout());
		javax.swing.JScrollPane eventMessageScroll = new javax.swing.JScrollPane(
				EventMessages);
		eventMessageArea.add(eventMessageScroll, java.awt.BorderLayout.CENTER);

		javax.swing.JPanel joinedAreas = new javax.swing.JPanel(
				new java.awt.BorderLayout());
		joinedAreas.add(messageArea, java.awt.BorderLayout.CENTER);
		joinedAreas.setEnabled(false);
		//joinedAreas.add(eventMessageArea, java.awt.BorderLayout.SOUTH);
		
		javax.swing.JPanel joinedPeers = new javax.swing.JPanel(
				new java.awt.BorderLayout());
		
		joinedPeers.setEnabled(false);
		
		joinedPeers.add(peerList,BorderLayout.CENTER);		
		joinedPeers.add(new JLabel("Online Peers"),BorderLayout.NORTH);
		
		JButton chatBut = new JButton();
		chatBut.addActionListener(new ChatRequest());
		chatBut.setText("VOIP Chat");
		
		JPanel southPanel = new JPanel(new BorderLayout());
		southPanel.add(Input, java.awt.BorderLayout.NORTH);
		southPanel.add(chatBut, java.awt.BorderLayout.SOUTH);

		javax.swing.JPanel contentPane = new javax.swing.JPanel(
				new java.awt.BorderLayout());
		contentPane.add(joinedPeers, BorderLayout.EAST);
		contentPane.add(joinedAreas, java.awt.BorderLayout.CENTER);
		//contentPane.add(Input, java.awt.BorderLayout.SOUTH);		
		contentPane.add(southPanel, java.awt.BorderLayout.SOUTH);

		contentPane.setOpaque(true);
		this.setContentPane(contentPane);

		setTitle("mySkype - " + instanceName);
		this.setVisible(true);
		WindowListener listen = new WindowListener();
		this.addWindowListener(listen);
		//chat.JoinGroup(chatGroup, chatName, this);
		//chat.CreateGroup(chatGroup);
	}
	
	private class WindowListener extends java.awt.event.WindowAdapter {
		public void windowClosing(java.awt.event.WindowEvent event) {
			System.out.println("Exiting ....");
			chatManager.closeNetwork();
			System.exit(0);
		}
	}
	
	public static void main(String[] args){
		System.setProperty("net.jxta.logging.Logging", "SEVERE");		
		//System.setProperty("net.jxta.logging.Logging", net.jxta.logging.Logging.MIN_SHOW_LEVEL.toString());
		
		//System.setProperty("net.jxta.level", "ERROR");
		
		//CommandLineMenu m = new CommandLineMenu();
		
		System.out.println("Type instance name");
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String input = "KobyKarin";
		
		try {
			input = br.readLine();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}				
		
		ChatGUI chat = new ChatGUI(input);
	}

	// FIXME marked due to ant errors
	
	//@Override
	public void actionPerformed(ActionEvent event) {
		if(event.getSource() == Input) {
		    //chat.SendMessage(Input.getText(), chatGroup);
			chatManager.createOutputPipe();
			Message msg = chatManager.createMessage(Input.getText());
			
			if (peerList.getSelectedIndex() != -1){
			
				String chosenPeerName = (String)listModel.get(peerList.getSelectedIndex());
				
				/*if (msg != null){
					chatManager.sendMessage(msg);				
				}*/
				try {
					PipeHolder.getInstance().getPipe(chosenPeerName).sendMessage(msg);
					
					Messages.append(chatManager.createMessageText(Input.getText()) + "\n");
					
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			else{
				chatManager.sendMessage(msg);								
			}
			
		    Input.setText(null);		   		   
		}
	}
	
	private class PeerListener implements JxtaChatListener{

		// FIXME marked due to ant errors
		
		// TODO Check what messages will discover peers
		
		//@Override
		public void jxtaChatEvent(JxtaChatEvent event) {
			//if (event.getSource() instanceof PeerNode){
				//peerList.getModel().
			if ((event.getSource() instanceof LoginMessage) && 
				!chatManager.getPeerName().equalsIgnoreCase(((LoginMessage)event.getSource()).getPeerName())){
			
				String peerName = ((LoginMessage)event.getSource()).getPeerName();
				
				if (!listModel.contains(peerName)){
					listModel.addElement(peerName);
				}
				
				/*if (!listModel.contains(event.getPeerName())){
					listModel.addElement(event.getPeerName());
					peers.put(event.getPeerName(), (PipeAdvertisement)event.getSource());
				}	*/			
			}
			else if (event.getSource() instanceof RegularMessage){
				RegularMessage rm = (RegularMessage)event.getSource();
				Messages.append(rm.getMessageText() + "\n");
			}
			else if (event.getSource() instanceof LogOutMessage){
				String name = ((LogOutMessage)event.getSource()).getPeerName();
				PipeHolder.getInstance().remove(name);
				listModel.removeElement(name);
				Messages.append(String.format(" **************** peer %s had loged out ***************\n", name));
			}
			else if (event.getSource() instanceof UserDiscoveredMessage){
				String name = ((UserDiscoveredMessage)event.getSource()).getPeerName();
				
				if (!listModel.contains(name)){
					listModel.addElement(name);
				}
			}
		}
		
	}
	
	private class MessageListener implements JxtaChatListener{

		// FIXME marked due to ant errors		
		
		//@Override
		public void jxtaChatEvent(JxtaChatEvent event) {
			Messages.append(event.getMessage() + "\n");			
		}
		
	}
	
	public String getSelectedPeerName(){
		return (String)listModel.getElementAt(peerList.getSelectedIndex());
	}
	
	/**
	 * Display a confirmation message for the chat invitation
	 * 
	 * @param peerName the name of the peer initiated the request
	 * @return the user response to the invitation (true - yes, false - no)
	 */
	public boolean respondChatInvitation(String peerName){
		
		return JOptionPane.showConfirmDialog(this,
                							   "Peer " + peerName + " wants to talk. approve?",
                							   "ChatInvitation",
                							   JOptionPane.YES_NO_OPTION,
                							   JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION;
	}
	
	public boolean respondChatCall(String peerName){
		
		return JOptionPane.showConfirmDialog(this,
                							   "Peer " + peerName + " wants to talk. approve?",
                							   "ChatInvitation",
                							   JOptionPane.YES_NO_OPTION,
                							   JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION;
	}
	
	public boolean presentInvitationResponse(Constants.ChatInvitaionResponseVals response){
		
		String peerName = (String)listModel.getElementAt(this.peerList.getSelectedIndex());
		boolean retVal = false;
		
		if (response.equals(ChatInvitaionResponseVals.BUSY)){
			JOptionPane.showMessageDialog(this, 
					"Peer " + peerName + " is busy and can't talk right know",
					"VoiceInvitationResponse",	                
	                JOptionPane.INFORMATION_MESSAGE);
		}
		else if (response.equals(ChatInvitaionResponseVals.REFUSE)){
			JOptionPane.showMessageDialog(this, 
					"Peer " + peerName + " refused the invitation",
					"VoiceInvitationResponse",	                
	                JOptionPane.INFORMATION_MESSAGE);
		}
		else if (response.equals(ChatInvitaionResponseVals.PEER_UNREACHABLE)){
			JOptionPane.showMessageDialog(this, 
					"Peer " + peerName + " is unreachable. try again later.",
					"VoiceInvitationResponse",	                
	                JOptionPane.INFORMATION_MESSAGE);
		}
		else if (response.equals(ChatInvitaionResponseVals.ACCEPT)){
			retVal = true;
		}
		
		return retVal;
	}
	
	/**
	 * Display the void chat screen, and start chating.
	 */
	public void startVoiceChat(boolean initLocally){
		
		startVoiceChat(initLocally, null);
	}
	
	public void startVoiceChat(boolean initLocally, String peerName){
		
		if (peerName == null){
			if (peerList.getSelectedIndex() != -1){
				peerName = (String)listModel.get(peerList.getSelectedIndex());
			}
			else{
				peerName = "";
			}
		}
		
		JDialog jd = new JDialog(this, "VoiceChat", true);
		
		voiceChatView = new VoJxtaDialogView(initLocally, peerName);
		
		jd.getContentPane().add(voiceChatView);
	    jd.pack();
	    jd.setLocationRelativeTo(this);
	    jd.setVisible(true);
	}
	
	public void updateChatScreen(){
		voiceChatView.remotePlaceCall();
	}

	/*private class MessageTextAreaListener extends java.awt.event.KeyAdapter{

		
		/*@Override
		public void keyPressed(KeyEvent e) {
			if (e.getKeyCode() == KeyEvent.VK_ENTER){
				System.out.println("in pressed. Enter was pressed");
			}
			
		}*/

	/*	@Override
		public void keyReleased(KeyEvent e) {
			if (e.getKeyCode() == KeyEvent.VK_ENTER){
				System.out.println("in released. Enter was pressed");
			}
			
		}

		@Override
		public void keyTyped(KeyEvent e) {
			if (e.getKeyCode() == KeyEvent.VK_ENTER){
				System.out.println("Enter was pressed");
			}
		}
		
	}*/
	
	private class ChatRequest implements ActionListener{
		
		public void actionPerformed(ActionEvent e) {
			if (peerList.getSelectedIndex() != -1){				
				String peerName = (String)listModel.getElementAt(peerList.getSelectedIndex());
				System.out.println("Sending invitation to peer " + peerName);
				
				chatManager.sendChatInvitation(peerName);
			}
			
		}
		
	}
}
